package com.dolphin.controller.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dolphin.base.BaseApiController;
import com.dolphin.commons.*;
import com.dolphin.commons.utils.WxLoginCacheUtil;
import com.dolphin.config.shiro.customToken.WxToken;
import com.dolphin.forest.weChat.WeChatOffiaccountForest;
import com.dolphin.forest.weChat.rep.WeChatForestResponse;
import com.dolphin.model.Role;
import com.dolphin.model.User;
import com.dolphin.service.RoleService;
import com.dolphin.service.UserService;
import com.dolphin.service.WeChatAdvancedService;
import com.dolphin.vo.WxLoginVO;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;

/**
 * 描述:
 * ${DESCRIPTION}
 *
 * @author 小海豚
 * @create 2023-05-25 22:57
 * 个人博客地址：https://www.nonelonely.com
 */
@RestController
@RequestMapping("/api/weChat")
@CrossOrigin
public class WeChatAdvancedController extends BaseApiController {
    private final static Logger LOGGER = LoggerFactory.getLogger(WeChatAdvancedController.class);

    @Value("${shiro.timeout}")
    private Long timeout;
    @Autowired
    private WeChatAdvancedService weChatAdvancedService;
    @Autowired
    private WeChatOffiaccountForest weChatOffiaccountForest;
    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;

    /*/**
     * @title 获取小程序二微码
     * @description [httpServletResponse]
     * @author 小海豚博客
     * @updateTime 2023/5/27 23:24
     * @throws
     */
    @GetMapping("/getShowQrcode")
    public ResponseBean getShowQrcode() throws Exception {
        return weChatAdvancedService.getShowqrcode();
    }

    /**
     * 根据uuid 查询缓存中当前小程序码的状态
     *
     * @param uuid
     * @return
     */
    @GetMapping("/getShowQrcode/{uuid}")
    public ResponseBean getQRStatus(@PathVariable String uuid) {
        String key = WxConstant.WX_QRCODE_SCENE + uuid;
        String value = WxLoginCacheUtil.getCacheValue(key);
        ResponseBean success = ResponseBean.success();
        HashMap<String, Object> map = new HashMap<>();
        if (StringUtil.isNotEmpty(value) && value.startsWith(WxConstant.WX_QRCODE_SUCCESS)) {
            String account = value.split("_")[1];
            WxToken wxToken = new WxToken(account);
            Subject subject = SecurityUtils.getSubject();
            subject.login(wxToken);
            User userByAccount = userService.getUserByAccount(account);
            String md5Hash = new Md5Hash(userByAccount.getPassword(), userByAccount.getSalt()).toString();
            String token = JwtUtils.sign(userByAccount.getAccount(), md5Hash);
            userByAccount.setPassword(null);
            userByAccount.setSalt(null);
            map.put("user", userByAccount);
            map.put("token", token);
            if (userByAccount.hasAdminPage()) {
                map.put("url", "/admin");
            } else {
                map.put("url", "/");
            }
            userService.updateLastLoginTime(userByAccount);
            subject.getSession().setTimeout(timeout * 1000 * 60);
            map.put(WxConstant.QR_STATUS, WxConstant.QR_STATUS_SUCCESS);
        } else if (StringUtil.isNotEmpty(value)) {
            map.put(WxConstant.QR_STATUS, value);
        } else {
            map.put(WxConstant.QR_STATUS, WxConstant.WX_QRCODE_EXPIRED);
        }
        success.setData(map);
        return success;
    }

    /**
     * 更新动态二维码登录的状态为已扫一扫
     */
    @GetMapping("/login")
    public ResponseBean login(String code, String scene) {
        LOGGER.info("login:{}", scene);
        String key = WxConstant.WX_QRCODE_SCENE + scene;
        String value = WxLoginCacheUtil.getCacheValue(key);
        if (StringUtils.isNotEmpty(value)) {
            WxLoginCacheUtil.putCacheValue(key, WxConstant.WX_QRCODE_SCAN, 3 * 60);
        }
        String appKey = OptionCacheUtil.getValue(Constants.WX_OFFIACCOUNT_APP_KEY);
        String appId = OptionCacheUtil.getValue(Constants.WX_OFFIACCOUNT_APP_ID);
        // 1.接收小程序发送的code
        // 2.开发者服务器 登录凭证校验接口 appi + appsecret + code
        WeChatForestResponse weChatForestResponse = weChatOffiaccountForest.wechatLogin(appId, appKey, code);
        // 3.接收微信接口服务 获取返回的参数
        String openid = weChatForestResponse.getOpenid();
        String sessionKey = weChatForestResponse.getSessionKey();
        WxLoginVO wxLoginVO = new WxLoginVO();
        wxLoginVO.setSessionKey(sessionKey);
        wxLoginVO.setOpenId(openid);
        return ResponseBean.success(wxLoginVO);
    }

    @PostMapping("/getWxUserInfo")
    public ResponseBean getWxUserInfo(@RequestBody WxLoginVO wxLoginVO) {

        LOGGER.info("getWxUserInfo:{}", JSON.toJSONString(wxLoginVO));

        // 用户非敏感信息：rawData
        String rawData = wxLoginVO.getRawData();
        String signature = wxLoginVO.getSignature();
        // 签名：signature
        JSONObject rawDataJson = JSON.parseObject(rawData);

        String openid = wxLoginVO.getOpenId();
        String sessionKey = wxLoginVO.getSessionKey();
        // 4.校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey)
        String signature2 = DigestUtils.sha1Hex(rawData + sessionKey);
        if (!signature.equals(signature2)) {
            return ResponseBean.fail("签名校验失败");
        }
        // 5.根据返回的User实体类，判断用户是否是新用户，是的话，将用户信息存到数据库；
        User user = userService.getUserByAccount("wx:" + openid);
        if (user == null) {
            // 用户信息入库
            String nickName = rawDataJson.getString("nickName");
            String avatarUrl = rawDataJson.getString("avatarUrl");
            user = new User();
            user.setAvatar(avatarUrl);
            user.setUserName(nickName + StringUtil.getUUID());
            user.setAccount("wx:" + openid);
            user.setPassword(StringUtil.getUUID());
            user.setStatus(Constants.USER_STATUS_DEFAULT);
            //设置默认角色
            String roleCode = OptionCacheUtil.getValue(Constants.EHCACHE_KEY_WEB_REGISTER_DEFAULT_ROLE);
            if (StringUtils.isBlank(roleCode)) {
                roleCode = Constants.ROLE_USER;
            }
            Role role = roleService.getRoleByCode(roleCode);
            user.setRoleId(role.getId());
            userService.add(user);
        }
        String md5Hash = new Md5Hash(user.getPassword(), user.getSalt()).toString();
        String token = JwtUtils.sign(user.getAccount(), md5Hash);
        //更新动态二维码登录的状态
        String scene = wxLoginVO.getScene();
        String key = WxConstant.WX_QRCODE_SCENE + scene;
        String value = WxLoginCacheUtil.getCacheValue(key);
        if (StringUtils.isNotEmpty(value)) {
            WxLoginCacheUtil.putCacheValue(key, WxConstant.WX_QRCODE_SUCCESS + "_" + user.getAccount(), 30);
        }
        return ResponseBean.success(token, user);
    }
}
